#ifndef _HACKBOY_H
#define _HACKBOY_H

#include <windows.h> 
#include <stdio.h>
#include <tlhelp32.h>

typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;

namespace HackBoyInterface
{
	union Param_t
	{
		int 	i;
		float 	f;
		DWORD	d;

		Param_t() { memset(this, 0, sizeof(Param_t)); }
		Param_t(int value) { i = value; }
		Param_t(float value) { f = value; }
		Param_t(DWORD value) { d = value; }
	};

	enum MessageType
	{
		IS_NUMERIC = 0x00,
		IS_TEXT = 0x01,
		IS_COMMAND = 0x02,
		IS_REQUEST = 0x04,
		IS_RESPONSE = 0x08
	};

	enum PipeCommands
	{
		//Pipe Control
		CA_DisconnectPipe = 0x001, CA_AliveRequest, CA_IsAlive,

		//Error Control
		CA_Error = 0x050,

		//Commands
		CA_CommandsBegin = 0x100,
		CA_TestCommand, CA_SetSpeed, CA_MoveTo, CA_UseItem, CA_SelectTarget, CA_UseSkill,
		CA_LootItem, CA_SummonPet, CA_TalkToNpc, CA_QuestAccept, CA_QuestReward, CA_DestroyItem,
		CA_RepairItems, CA_ChangeRealm, CA_UseItemByItemId, CA_FollowPlayer, CA_Interact,
		CA_AutoLootOnOff,
		CA_CommandsEnd,

		//Requests
		CA_RequestsBegin = 0x300,
		CA_TestRequest, CA_GetCurrentTargetId, CA_PlayerIterFirst, CA_PlayerIterNext, CA_GetItemIdByIndex,
		CA_GetCoords, CA_GetDistFromPlayerToPlayer, CA_GetPlayerType, CA_GetPlayerName, CA_GetMyId,
		CA_GetHp, CA_GetPetPlayerId, CA_GetSelectedQuestId, CA_GetPetHp, CA_GetPlayerIdByName,
		CA_GetServerRealmInfo, CA_GetPartySize, CA_GetPartyMemberInfo, CA_GetClosestPlayerByName,
		CA_GetIsDead,
		CA_RequestsEnd
	};

	struct BaseMessage
	{
		word header;
		word type;
		Param_t param1, param2, param3, param4, param5;
		char buffer[100];

		BaseMessage() { memset(this, 0, sizeof(BaseMessage)); }
	};

	int FloatToInt(float fFloat);

	class HackBoy
	{
	private:
		HANDLE _pipe;
		HANDLE _mutex;
		DWORD _cbWritten;
		DWORD _cbRead;

	public:
		BaseMessage* InBuffer;
		char* sClientTitle;
		char* sClientClass;
		char* sCharName;

		HackBoy(char* inName = NULL)
		{
			_pipe = NULL;
			_mutex = CreateMutex(NULL, false, NULL);
			_cbWritten = 0;
			_cbRead = 0;
			InBuffer = new BaseMessage();
			sClientTitle = "Battle of Immortals-";
			sClientClass = "_PERFECTWORLD_HUGEROCK";
			sCharName = inName;
		}

		void Disconnect();
		void Cmd(PipeCommands uMsg, int param1 = 0, int param2 = 0, int param3 = 0, int param4 = 0, int param5 = 0, char* buffer = NULL);
		void Cmd(PipeCommands uMsg, char* buffer, int param1 = 0, int param2 = 0, int param3 = 0, int param4 = 0, int param5 = 0);
		BaseMessage* CmdCB(PipeCommands uMsg, int param1 = 0, int param2 = 0, int param3 = 0, int param4 = 0, int param5 = 0, char* buffer = NULL);
		BaseMessage* CmdCB(PipeCommands uMsg, char* buffer, int param1 = 0, int param2 = 0, int param3 = 0, int param4 = 0, int param5 = 0);
		void MoveTo(float X, float Y, int MapId = 0);

	private:
		bool IsPipeCreated();
		bool Connect();
		bool SendMsg(MessageType msgType, PipeCommands uMsg,
			Param_t param1 = Param_t(), Param_t param2 = Param_t(), Param_t param3 = Param_t(),
			Param_t param4 = Param_t(), Param_t param5 = Param_t(), char* buffer = NULL);
		void SetDebugPrivilege();
	};
};

#endif